""" 根据原版基础数据，生成摆渡车任务，保存为csv格式的total_tasks.csv """
import pandas as pd 
import numpy as np 
from copy import deepcopy

np.random.seed(0)
flt_data = pd.read_excel(".\\data\\原版数据\\航班数据.xlsx") # 航班计划表
flt_layout = pd.read_excel(".\\data\\原版数据\\舱位布局.xlsx", index_col="type")  # 机舱布局，用以计算乘客人数
flt_run_time = pd.read_excel(".\\data\\原版数据\\机坪运行时间.xlsx", "机坪运行时间", header= 1) # 机坪运行时间

# 处理数据：
# 飞机布局：
flt_layout.fillna(0, inplace=True)
flt_layout = flt_layout.T.to_dict() # 生成机舱布局字典
# print(flt_layout)

# 机坪运行时间：
flt_run_time.index = flt_run_time["gate"] # 生成机坪转移时间矩阵


# 航班计划表
flt_data["进出港类型"]= flt_data["进出港类型"].apply(lambda x: 1 if x == "进港" else 0) # 进出港替换为1,0
# flt_data.index = flt_data["航班日期"].map(str) + "_" + flt_data["航班号"]

flt_data_dict = flt_data.T.to_dict() # 航班信息转dict


# 对每个航班生成任务
def build_task(flt_data_dict, flt_layout, flt_run_time):
    """
    input: flt_data_dict[flt_plan], flt_layout[get psg_numbers], flt_run_time[get job time]
    output: tasks  
    """
    total_task = [] # 初始化任务列表 

    for id in flt_data_dict:
        veh_task = deepcopy([]) # 一个航班的摆渡任务
        # 计算旅客人数
        flt_info = flt_data_dict[id]

        flt_info["旅客人数"]  = compute_psgs_number(flt_info, flt_layout, rate = 0.8)

        # 根据乘客数目，确定摆渡车数量
        vip_veh_number = compute_veh_number(flt_info["旅客人数"][0], is_vip = True)
        norm_veh_number = compute_veh_number(flt_info["旅客人数"][1], is_vip = False)

        # 根据机位计算运行时间
        run_time = compute_run_time(flt_info, flt_run_time)

        # 生成vip任务：
        for i in range(vip_veh_number):
            sub_task = {} # 初始化
            
            sub_task["date"] = flt_info["航班日期"]
            sub_task["flight_id"] = flt_info["航班号"]
            sub_task["veh_order"] = i+1 # i车次

            # 处理任务开始结束时间
            # 按出港进港区分
            # 根据进出港，确定摆渡车任务时间
            sub_task["ready_time"],sub_task["start_time"],sub_task["end_time"]= compute_task_time(flt_info, i+1, True, run_time)
            sub_task["is_vip"] = True

            veh_task.append(sub_task)

        
        # 生成普通任务：
        for i in range(norm_veh_number):
            sub_task = {} # 初始化
            
            sub_task["date"] = flt_info["航班日期"]
            sub_task["flight_id"] = flt_info["航班号"]
            sub_task["veh_order"] = i+1 # i车次

            # 处理任务开始结束时间
            # 按出港进港区分
            # 根据进出港，确定摆渡车任务时间
            sub_task["ready_time"],sub_task["start_time"],sub_task["end_time"]= compute_task_time(flt_info, i+1, False, run_time)

            sub_task["is_vip"] = False

            veh_task.append(sub_task)
            aaa = 1
        total_task += veh_task
    return total_task
        # 生成任务数据结构

def compute_task_time(flt_info, veh_order, is_vip, run_time):
    
    # 处理进出港
    if flt_info["进出港类型"] == 1: # 进港
        # 执行时间
        flt_time = flt_info["STA"]
        
        # vip任务时间
        
        if is_vip:    
            if veh_order == 1:
                ready_time = flt_time - pd.Timedelta(5, unit = "m")
                start_time = flt_time + pd.Timedelta(13, unit= "m")
                end_time = start_time + pd.Timedelta(1.5 * run_time + 1, "m" )
            
            if veh_order == 2:
                ready_time = flt_time
                start_time = flt_time + pd.Timedelta(14, unit= "m")
                end_time = start_time + pd.Timedelta(1.5 * run_time + 1, "m" )
            
            if veh_order == 3:
                ready_time = flt_time + pd.Timedelta(5, unit = "m")
                start_time = flt_time + pd.Timedelta(15, unit= "m")
                end_time = start_time + pd.Timedelta(1.5 * run_time + 1, "m" )

            return ready_time, start_time, end_time


        # 普通任务时间
        elif not is_vip:
            if veh_order == 1:
                ready_time = flt_time - pd.Timedelta(5, unit = "m")
                start_time = flt_time + pd.Timedelta(13, unit= "m")
                end_time = start_time + pd.Timedelta(1.5 * run_time + 1, "m" )
            
            if veh_order == 2:
                ready_time = flt_time 
                start_time = flt_time + pd.Timedelta(15, unit= "m")
                end_time = start_time + pd.Timedelta(1.5 * run_time + 1, "m" )
            
            if veh_order == 3:
                ready_time = flt_time + pd.Timedelta(5, unit = "m")
                start_time = flt_time + pd.Timedelta(17, unit= "m")
                end_time = start_time + pd.Timedelta(1.5 * run_time + 1, "m" )
            
            if veh_order == 4:
                ready_time = flt_time + pd.Timedelta(5, unit = "m")
                start_time = flt_time + pd.Timedelta(19, unit= "m")
                end_time = start_time + pd.Timedelta(1.5 * run_time + 1, "m" )

            return ready_time, start_time, end_time
    
        # 处理出港航班：
    if flt_info["进出港类型"] == 0: # 进港
        # 执行时间
        flt_time = flt_info["STD"]
            
        # vip任务时间
        if is_vip:    
            if veh_order == 1:
                
                ready_time = flt_time - pd.Timedelta(35, unit = "m")
                start_time = flt_time - pd.Timedelta(25, unit= "m")
                end_time = start_time + pd.Timedelta(2 * run_time + 1, "m" )
            
            if veh_order == 2:
                ready_time = flt_time - pd.Timedelta(25, unit= "m") 
                start_time = flt_time - pd.Timedelta(20, unit= "m")
                end_time = start_time + pd.Timedelta(2 * run_time + 1, "m" )
            
            if veh_order == 3:
                ready_time = flt_time - pd.Timedelta(20, unit = "m")
                start_time = flt_time - pd.Timedelta(5, unit= "m")
                end_time = start_time + pd.Timedelta(2 * run_time + 1, "m" )

            return ready_time, start_time, end_time


        # 普通任务时间
        elif not is_vip:
            if veh_order == 1:
                ready_time = flt_time - pd.Timedelta(35, unit = "m")
                start_time = flt_time - pd.Timedelta(25, unit= "m")
                end_time = start_time + pd.Timedelta(2 * run_time + 1, "m" )
            
            if veh_order == 2:
                ready_time = flt_time - pd.Timedelta(25, unit= "m")
                start_time = flt_time - pd.Timedelta(19, unit= "m")
                end_time = start_time + pd.Timedelta(2 * run_time + 1, "m" )
            
            if veh_order == 3:
                ready_time = flt_time - pd.Timedelta(19, unit = "m")
                start_time = flt_time - pd.Timedelta(12, unit= "m")
                end_time = start_time + pd.Timedelta(2 * run_time + 1, "m" )
            
            if veh_order == 4:
                ready_time = flt_time - pd.Timedelta(12, unit = "m")
                start_time = flt_time - pd.Timedelta(5, unit= "m")
                end_time = start_time + pd.Timedelta(2 * run_time + 1, "m" )

            return ready_time, start_time, end_time



def compute_run_time(flt_info, flt_run_time, terminal = "N1"): # 预设N1为航站楼
    """ 生成机坪运行时间"""
    try:
        position = flt_info["机位"]
        run_time = flt_run_time.loc[position][terminal]
    except:
        run_time = np.random.randint(5,22)
        return run_time


def compute_psgs_number(flight,flt_layout, rate) -> list:
    """计算乘客数量"""
    if flight["机型"] == "789":
        flight["机型"] = "B"+flight["机型"]

    if flight["机型"] == "332" or flight["机型"] == "321" or flight["机型"] == "320" or flight["机型"] == "333" or flight["机型"] == "319":
        flight["机型"] = "A"+flight["机型"]

    if flight["机型"] == "77W" or flight["机型"] == "772" or flight["机型"] == "73K" or flight["机型"] == "739":
        flight["机型"] = "B"+flight["机型"]

    flt_layout_info = flt_layout[flight["机型"]]
    max_vip = flt_layout_info["F"]+flt_layout_info["J,C"]
    max_norm = flt_layout_info["G"]+flt_layout_info["Y"]
    
    _vip = int(max_vip * rate)
    _norm = int(max_norm * rate) 

    return [_vip, _norm]

def compute_veh_number(psgs_number, is_vip):
    
    # vip 车数目
    if  is_vip:
        veh_number = int(psgs_number / 33) + 1
        return veh_number
        
    # 普通车数目 
    else:
        veh_number = psgs_number//80
        if psgs_number % 80 <= 10:
            return veh_number
        else:
            return veh_number


if __name__ == "__main__":
    total_task = build_task(flt_data_dict, flt_layout, flt_run_time)
    x = pd.DataFrame(total_task).sort_values(by='ready_time')
    
    x.to_csv(r"\data\total_tasks.csv")




